import { ResConfig } from "../SysConfig/SysConfig";



const { ccclass, property } = cc._decorator;

@ccclass
export default class ResManage extends cc.Component {

    public static Instance: ResManage = null;

    onLoad() {
        if (ResManage.Instance == null) {
            ResManage.Instance = this;
        }
        else {
            this.destroy();
            return;
        }
    }

    /**
     * 加载配置的AB包
     * @param bundleData AB包数组名称 
     * @param onProgress 加载进度回调
     * @param onComplete 加载完成回调
     */
    public loadAllBoundles(bundleData: ResConfig.BundleData[] | ResConfig.BundleData, onProgress: Function = null, onComplete: Function = null): void {
        if (bundleData == null) { return };

        let curCount: number = 0;
        let totalCount: number = Array.isArray(bundleData) ? bundleData.length : 1;

        if (Array.isArray(bundleData)) {
            bundleData.forEach((value, index) => {
                let remoteUrl: string = value.isRemote ? ResConfig.BundlePaht : '';
                cc.assetManager.loadBundle(remoteUrl + value.bundleName, (err: Error, bundle: cc.AssetManager.Bundle) => {
                    if (err) {
                        console.error(err);
                        return;
                    }

                    curCount++;
                    if (onProgress) {
                        onProgress(curCount, totalCount);
                    }

                    if (curCount >= totalCount) {
                        if (onComplete) {
                            onComplete();
                        }
                    }
                })
            });
        }
        else {
            let remoteUrl: string = bundleData.isRemote ? ResConfig.BundlePaht : '';
            cc.assetManager.loadBundle(remoteUrl + bundleData.bundleName, (err: Error, bundle: cc.AssetManager.Bundle) => {
                if (err) {
                    console.error(err);
                    return;
                }

                curCount++;
                if (onProgress) {
                    onProgress(curCount, totalCount);
                }

                if (curCount >= totalCount) {
                    if (onComplete) {
                        onComplete();
                    }
                }
            })
        }
    }
    /**
     * 释放所有AB资源包
     * @param bundleData AB包数组名称  注意: 不要随意调用
     * @returns 
     */
    public releaseaAllBoundles(bundleData: ResConfig.BundleData[] | ResConfig.BundleData) {
        if (bundleData == null) { return }

        if (Array.isArray(bundleData)) {
            bundleData.forEach((value, index) => {
                let bundle = cc.assetManager.getBundle(value.bundleName);
                if (bundle) {
                    bundle.releaseAll();// 释放所有属于 Asset Bundle 的资源
                    cc.assetManager.removeBundle(bundle);
                }
            })
        }
        else {
            let bundle = cc.assetManager.getBundle(bundleData.bundleName);
            if (bundle) {
                bundle.releaseAll();// 释放所有属于 Asset Bundle 的资源
                cc.assetManager.removeBundle(bundle);
            }
        }
    }


    /**
     * 提前载AB包中的资源
     * @param bundleData    AB包名称
     * @param type          资源类型
     * @param onProgress    进度回调
     * @returns 
     */
    public advLoadAssetFromBundle(bundleData: ResConfig.BundleData, type: typeof cc.Asset, onProgress: Function): Promise<null> {
        if (bundleData == null) { return }

        return new Promise((resolve, reject) => {
            let bundle = cc.assetManager.getBundle(bundleData.bundleName);
            if (bundle) {
                let infos = bundle.getDirWithPath("/");
                let curCount: number = 0;
                let totalCount: number = infos.length;
                infos.forEach((value, index) => {
                    bundle.load(value.path, type, (err: Error, asset: cc.Asset) => {
                        if (err) {
                            curCount++;
                            console.error(`预加载${value.path}失败`, err);
                        }
                        else {
                            curCount++;
                            asset.addRef();
                            if (onProgress) {
                                onProgress(curCount, totalCount);
                            }
                            if (curCount >= totalCount) {
                                resolve(null);
                            }
                        }
                    })
                })
            }
            else {
                console.error(`bundle <${bundleData}> 不存在!!! `);
                resolve(null);
            }
        })
    }
    /**
     * 同步获取资源接口, 上面已经加载好资源
     * @param bundleData AB包名称
     * @param paths    资源路径
     * @param type   资源类型
     * @returns 
     */
    public getAssetFomeCache(bundleData: ResConfig.BundleData, paths: string, type: typeof cc.Asset): any {
        if (bundleData == null) { return }

        let bundle = cc.assetManager.getBundle(bundleData.bundleName);
        if (!bundle) {
            return null;
        }

        return bundle.get(paths, type);
    }


    /**
     * 从AB包中获取资源
     * @param bundleData AB包名称
     * @param paths  资源路径
     * @param type   资源类型
     * @returns 
     */
    public loadAssetByBoundle(bundleData: ResConfig.BundleData, paths: string, type: typeof cc.Asset, onComplete: Function) {
        if (bundleData == null) { return }

        let abBundle = cc.assetManager.getBundle(bundleData.bundleName);
        if (abBundle) {
            abBundle.load(paths, type, (err: Error, asset: cc.Asset) => {
                if (err) {
                    console.error(err);
                    onComplete(err, asset);
                }
                else {
                    asset.addRef();
                    if (onComplete) {
                        onComplete(err, asset);
                    }
                }
            })
        }
        else {
            console.error(`bundle <${bundleData.bundleName}> 不存在!!! `);
        }
    }
    /**
     * 从AB包中释放资源
     * @param bundleData AB包名称
     * @param paths  资源路径
     * @param type   资源类型
     * @returns 
     */
    public releaseAssetByBoundle(bundleData: ResConfig.BundleData, paths: string, type: typeof cc.Asset) {
        if (bundleData == null) { return }

        let bundle = cc.assetManager.getBundle(bundleData.bundleName);
        if (!bundle) {
            return;
        }
        let aseet = bundle.get(paths, type);
        if (aseet) {
            aseet.decRef();
        }
    }


    // update (dt) {}
}
